﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web;
using System.Web.Security;
using ETSClient.com.allinpay.ets.client;
using QDT.Common;
using QDT.Payment.AllInPay.Api;

namespace QDT.Payment.AllInPay
{
    public class AllInPayPayment : AbstractPayment
    {

        private const string Gateway = "https://service.allinpay.com/gateway/index.do";
        //        private const string Gateway = "http://ceshi.allinpay.com/gateway/index.do";

        public override string Key { get { return GetType().Name; } }

        public override string Name { get { return "通联支付"; } }

        public override void InchargeRequest(PaymentOrder order)
        {
            var payment = new RequestOrder();

            payment.setPickupUrl(order.ReturnUrl.Replace("https", "http"));
            payment.setReceiveUrl(order.NoticeUrl.Replace("https", "http"));
            payment.setOrderNo(order.PaymentNo);
            payment.setOrderAmount((order.Money * 100).ToString("0"));
            payment.setOrderDatetime(order.CreateTime.ToString("yyyyMMddHHmmss"));

            //            payment.setPayerName(order.UserName);
            //            payment.setPayerIDCard(order.UserIDCard);

            payment.setMerchantId("109338511507002");
            payment.setKey("1234567890");

            //            payment.setMerchantId("100020091218001");
            //            payment.setKey("1234567890");

            #region 固定值
            payment.setVersion("v1.0"); //接口版本
            payment.setOrderExpireDatetime("60");//60分钟过期
            payment.setLanguage("1"); //简体中文
            payment.setOrderCurrency("0"); //人民币
            payment.setInputCharset("1"); //字符集 UTF-8
            payment.setSignType(("1")); //签名类型
            payment.setPayType(("0")); //支付方式
            payment.setIssuerId(""); //发卡方代码
            #endregion

            #region 非必填项
            payment.setPayerEmail("");
            payment.setPayerTelephone("");
            payment.setPid("");
            payment.setProductName("");
            payment.setProductPrice((""));
            payment.setProductNum((""));
            payment.setProductId("");
            payment.setProductDesc("");
            payment.setProductDescription("");
            payment.setExt1("");
            payment.setExt2("");
            payment.setExtTL("");
            payment.setPan("");
            payment.setTradeNature("");
            #endregion

            string signMsg = payment.doSign();
            var stringBuilder = new StringBuilder();

            #region 生成HTML
            stringBuilder.Append(CreateField("pickupUrl", payment.getPickupUrl()));
            stringBuilder.Append(CreateField("receiveUrl", payment.getReceiveUrl()));

            //            stringBuilder.Append(CreateField("payerName", payment.getPayerName()));
            //            stringBuilder.Append(CreateField("payerIDCard", payment.getPayerIDCard()));

            stringBuilder.Append(CreateField("orderExpireDatetime", payment.getOrderExpireDatetime()));
            stringBuilder.Append(CreateField("language", payment.getLanguage()));

            stringBuilder.Append(CreateField("inputCharset", payment.getInputCharset()));
            stringBuilder.Append(CreateField("version", payment.getVersion()));
            stringBuilder.Append(CreateField("signType", payment.getSignType()));
            stringBuilder.Append(CreateField("merchantId", payment.getMerchantId()));
            stringBuilder.Append(CreateField("orderNo", payment.getOrderNo()));
            stringBuilder.Append(CreateField("orderAmount", payment.getOrderAmount()));
            stringBuilder.Append(CreateField("orderCurrency", payment.getOrderCurrency()));
            stringBuilder.Append(CreateField("orderDatetime", payment.getOrderDatetime()));
            stringBuilder.Append(CreateField("payType", payment.getPayType()));
            stringBuilder.Append(CreateField("signMsg", signMsg));
            #endregion

            SubmitPaymentForm(CreateForm(stringBuilder.ToString(), Gateway));
        }

        public override bool InchargeQueryRequest(PaymentOrder order)
        {

            const string key = "1234567890";
            const string merchantId = "109338511507002";
            var orderNo = order.PaymentNo;
            var orderDatetime = order.CreateTime.ToString("yyyyMMddHHmmss");
            var queryDatetime = DateTime.Now.ToString("yyyyMMddHHmmss");

            var signSrc =
                "merchantId={0}&version=v1.5&signType=0&orderNo={1}&orderDatetime={2}&queryDatetime={3}&key={4}"
                .FormatWith(merchantId, orderNo, orderDatetime, queryDatetime, key);

            var querySignMsg = FormsAuthentication.HashPasswordForStoringInConfigFile(signSrc, "MD5");

            var postData =
                "merchantId={0}&version=v1.5&signType=0&orderNo={1}&orderDatetime={2}&queryDatetime={3}&signMsg={4}"
                    .FormatWith(merchantId, orderNo, orderDatetime, queryDatetime, querySignMsg);

            byte[] tRequestMessage = System.Text.ASCIIEncoding.UTF8.GetBytes(postData);
            HttpWebRequest tWebRequest = null;
            BufferedStream tRequestStream = null;
            HttpWebResponse tWebResponse = null;
            Byte[] tResponseByteArray = null;

            try
            {
                tWebRequest = (HttpWebRequest)WebRequest.Create(Gateway);
                tWebRequest.Method = "POST";
                tWebRequest.ProtocolVersion = HttpVersion.Version11;
                tWebRequest.ContentType = "application/x-www-form-urlencoded";
                tWebRequest.KeepAlive = false;
                tWebRequest.ServicePoint.Expect100Continue = false;
                tWebRequest.ReadWriteTimeout = 20000;
                tWebRequest.Timeout = 20000;
                tWebRequest.ContentLength = tRequestMessage.Length;
                tRequestStream = new BufferedStream(tWebRequest.GetRequestStream());
                if (!tRequestStream.CanWrite)
                {
                    //不能连接serverUrl
                    throw new Exception("不能建立连接");
                }
                tRequestStream.Write(tRequestMessage, 0, tRequestMessage.Length);
                tRequestStream.Flush();
                tWebResponse = (HttpWebResponse)tWebRequest.GetResponse();
                if (tWebResponse.StatusCode != HttpStatusCode.OK)
                {
                    //交易平台未成功处理请求
                    throw new Exception("交易平台未成功处理请求");
                }
                Stream tReceiveStream = tWebResponse.GetResponseStream();
                StreamReader tStreamReader = new StreamReader(tReceiveStream);
                String tLine = null;
                String tResponseMessage = "";
                while ((tLine = tStreamReader.ReadLine()) != null)
                {
                    tResponseMessage += tLine;
                }
                tResponseByteArray = System.Text.ASCIIEncoding.UTF8.GetBytes(tResponseMessage);
                var responseString = System.Text.Encoding.UTF8.GetString(tResponseByteArray);

                string[] parameters = responseString.Split('&');

                var result = false;

                foreach (var param in parameters)
                {
                    string[] var = param.Split('=');
                    if (var.Length == 2)
                    {
                        string name = var[0];
                        string value = var[1];

                        if (name.Equals("payResult") && value.Equals("1"))
                        {
                            result = true;
                        }
                    }
                }

                return result;
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                if (tRequestStream != null)
                {
                    tRequestStream.Close();
                }
                if (tWebResponse != null)
                {
                    tWebResponse.Close();
                }
            }

        }

        public override void CarryRequest(IEnumerable<CarryOrder> orders)
        {
            foreach (var order in orders)
            {
                CarryRequest(order);
            }
        }

        public override bool CarryRequest(CarryOrder order)
        {

            #region 正式
            const string gateway = "https://tlt.allinpay.com/aipg/ProcessServlet";
            var signCert = new X509Certificate2(("D:/allinpay/20070300000114205.p12"), "111111");
            var verifyCert = new X509Certificate2(("D:/allinpay/allinpay-pds.cer"));
            const string useName = "20070300000114205";
            const string password = "111111";
            const string businessCode = "09900";
            const string merchantId = "200703000001142";
            #endregion

            #region 测试
            //            const string gateway = "https://113.108.182.3/aipg/ProcessServlet";
            //            var signCert = new X509Certificate2("D:/allinpay/ceshi/20060400000044502.p12", "111111");
            //            var verifyCert = new X509Certificate2("D:/allinpay/ceshi/allinpay-pds.cer");
            //            const string useName = "20060400000044502";
            //            const string password = "111111";
            //            const string businessCode = "09900";
            //            const string merchantId = "200604000000445";
            #endregion

            var aipg = new AIPG
            {
                url = gateway,
                SigneCert = signCert,
                VerifyCert = verifyCert
            };

            TradeRequest req = new BatchPayRequest(useName, password, "C" + order.OrderSn, 5, businessCode, merchantId);
            req.AddDetail(OrderToDetail(order));

            var resp = AsynSendReq(aipg, req);

            return resp;

        }

        public override int CarryQueryRequest(string orderSn)
        {
            #region 正式
            const string gateway = "https://tlt.allinpay.com/aipg/ProcessServlet";
            var signCert = new X509Certificate2(("D:/allinpay/20070300000114205.p12"), "111111");
            var verifyCert = new X509Certificate2(("D:/allinpay/allinpay-pds.cer"));
            const string useName = "20070300000114205";
            const string password = "111111";
            const string merchantId = "200703000001142";
            #endregion

//            #region 测试
//                        const string gateway = "https://113.108.182.3/aipg/ProcessServlet";
//                        var signCert = new X509Certificate2("D:/allinpay/ceshi/20060400000044502.p12", "111111");
//                        var verifyCert = new X509Certificate2("D:/allinpay/ceshi/allinpay-pds.cer");
//                        const string useName = "20060400000044502";
//                        const string password = "111111";
//                        const string merchantId = "200604000000445";
//            #endregion

            var aipg = new AIPG
            {
                url = gateway,
                SigneCert = signCert,
                VerifyCert = verifyCert
            };

            var qtranpkg = new QTransRetPackage { Merid = merchantId, Querysn = orderSn, Status = "2", Type = "1" };
            var qtransreq = new QTransRetRequest(qtranpkg, useName, password);

            var resp = aipg.Send(qtransreq);

            var result = resp.Trans_ret_msg;

            if (result.Contains("处理成功"))
            {
                return 1;
            }
            if (result.Contains("处理失败"))
            {
                return -1;
            }

            return 0;

        }

        public override bool VerifyNotify(NameValueCollection form, out object order)
        {
            var result = new PaymentResult();

            result.setMerchantId(form["merchantId"]);
            result.setVersion(form["version"]);
            result.setLanguage(form["language"]);
            result.setSignType(form["signType"]);
            result.setPayType(form["payType"]);
            result.setIssuerId(form["issuerId"]);
            result.setPaymentOrderId(form["paymentOrderId"]);
            result.setOrderNo(form["orderNo"]);
            result.setOrderDatetime(form["orderDatetime"]);
            result.setOrderAmount(form["orderAmount"]);
            result.setPayDatetime(form["payDatetime"]);
            result.setPayAmount(form["payAmount"]);
            result.setExt1(form["ext1"]);
            result.setExt2(form["ext2"]);
            result.setPayResult(form["payResult"]);
            result.setErrorCode(form["errorCode"]);
            result.setReturnDatetime(form["returnDatetime"]);
            result.setSignMsg(form["signMsg"]);

            result.setKey("R0SW2u0mlb");
            result.setCertPath("D:/allinpay/TLCert.cer");

            //            result.setKey("1234567890");
            //            result.setCertPath(HttpContext.Current.Server.MapPath("../Content/cert/ceshi/TLCert.cer"));

            order = new PaymentOrder
            {
                PaymentNo = result.getOrderNo(),
                Money = Convert.ToDecimal(result.getOrderAmount()) / 100,
            };

            var verifyResult = result.verify();
            return verifyResult;
        }

        public override bool VerifyNotify(NameValueCollection form, out string returnContent, out object order)
        {
            var isOk = VerifyNotify(form, out order);
            returnContent = isOk ? "ok" : "error";
            return isOk;
        }

        protected static DetailRequest OrderToDetail(CarryOrder order)
        {
            return new DetailRequest
            {
                Sn = order.OrderSn,
                Amount = Convert.ToInt64(order.Amount * 100),
                BankCode = order.BankCode,
                AccountNo = order.BankAccount,
                AccountName = order.AccountName,
                ID = order.IdCardNo,
                Tel = order.PhoneNo,
                Province = order.Province,
                City = order.City,
                BankName = order.BankZone,
                IDType = (IDType)order.IdType,
                Currency = (Currency)order.Currency,
                AccountProp = (AccountProp)order.AccountProp,
                AccountType = (AccountType)order.AccountType,
                Remark = order.Remark,
                UnionBank = order.UnionBank
            };
        }

        private bool AsynSendReq(AIPG aipg, TradeRequest req)
        {
            var result = false;
            try
            {
                Response resp = aipg.Send(req);
                if (resp != null && resp.ErrMsg.Contains("受理成功"))
                {
                    result = true;
                }
            }
            catch (Exception e)
            {
                return false;
            }
            return result;
        }

    }
}
